package org.foreveross.que.applicationImpl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.lang3.StringUtils;
import org.foreveross.que.entity.MenuEntity;
import org.foreveross.que.entity.SystemEntity;
import org.foreveross.que.infra.MenuRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.foreveross.que.application.TreeMenuApplication;
//import com.foreveross.feedback.infra.RoleMenuRRepository;
import org.foreveross.que.vo.IndexVo;
import org.foreveross.que.vo.TreeChildVo;
import org.foreveross.que.vo.TreeManagerVo;

/**
 * 该类把树转载进内存里面，直接操作内存
 * 
 * @author lyq
 * 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Service
public class TreeMenuApplicationImpl implements TreeMenuApplication {

	@Autowired
	MenuRepository menuRepository;
	
	// @Autowired RoleMenuRRepository roleMenuRRepository;

	/**
	 * List包含两个对象 ： 一个所有系统有效菜单集合 Map <String,TreeChildVo> <节点id，对应节点> ;
	 * 一个有效菜单子节点集合 Map <String ,Set<TreeChildVo>> <父节点id，对应节点下级节点集合>
	 **/
	public Map<String, List<Map>> allSysMenus = new HashMap<String, List<Map>>();

	// /*所有有效菜单的集合*/
	// private Map <String,TreeChildVo> menus = new
	// HashMap<String,TreeChildVo>();
	// /*已根据父类划分的集合*/
	// Map <String ,Set<TreeChildVo>> assortChild = new HashMap<String,
	// Set<TreeChildVo>>();

	// @Override
	// public Map <String,TreeChildVo> getMenus(String sysType) throws Exception
	// {
	// // TODO Auto-generated method stub
	// List<Map> list = allSysMenus.get(sysType);
	// if(list==null){
	// this.reloadMenus(sysType);
	// }
	// return (Map <String,TreeChildVo>)list.get(0);
	// }

	@Override
	public void reloadMenus(String sysType) throws Exception {
		List<Map> list = allSysMenus.get(sysType);
		if (list == null) {
			if(this.getSystemEntity(sysType)==null){
				throw new Exception("【sysType】该系统类型不存在，请联系管理员。");
			}
			list = new ArrayList<Map>();
			allSysMenus.put(sysType, list);
			list.add(new HashMap<String, TreeChildVo>());
			list.add(new HashMap<String, List<TreeChildVo>>());

		}
		Map<String, TreeChildVo> menus = (Map<String, TreeChildVo>) list.get(0);
		Map<String, List<TreeChildVo>> assortChild = (Map<String, List<TreeChildVo>>) list
				.get(1);
		List<MenuEntity> temps = menuRepository.getMenus(sysType);
		menus.clear();
		assortChild.clear();
		for (MenuEntity menu : temps) {
			menus.put(menu.getCode() + "", new TreeChildVo(menu));
		}
		assortChild(sysType);
	}

	@Transactional
	@Override
	public MenuEntity addMenu(TreeManagerVo vo) throws Exception {
		MenuEntity entity = vo.getEntity();
		entity.setSysType(vo.getSysType());
		
		loadEntityBaseParam(entity);
		this.menuRepository.create(entity);
		updateParentChildrenOrderId(vo);
		this.reloadMenus(entity.getSysType());
		return entity;
	}
	
	@Transactional
	@Override
	public MenuEntity addMenu(IndexVo vo) throws Exception {
		MenuEntity entity = vo.getMenu();
		entity.setDescription("小区初建啊");
		entity.setSysType(vo.getSysType());
		loadEntityBaseParam(entity);
		TreeChildVo pnode = this.getTreeById(entity.getPid(), entity.getSysType());
		pnode = pnode==null?this.getSysChildVo(entity.getSysType(), "null"):pnode;
		int i = pnode==null?0:pnode.getChildren().size();
		if(i==0){
			entity.setOrderId(0);
		}else{//自动排序到统计父节点最后一级
			entity.setOrderId(pnode.getChildren().get(i-1).getOrderId()+1);
		}
		this.menuRepository.create(entity);
		this.reloadMenus(entity.getSysType());
		return entity;
	}

	private void loadEntityBaseParam( MenuEntity entity)
			throws Exception {
		Date currDate = new Date();
		entity.setCreateTime(currDate);
		entity.setLastTime(currDate);
		String pid = StringUtils.isBlank(entity.getPid()) ? null : entity.getPid();
		entity.setPid(pid);
		entity.setState(1);
		if (StringUtils.isBlank(entity.getSysType())) {
			throw new Exception("MenuEntity.sysType is null");
		}
	}

	@Transactional
	@Override
	public MenuEntity update(TreeManagerVo vo) throws Exception {
		MenuEntity entity = vo.getEntity();
		MenuEntity dbEntity = this.findEntity(entity.getCode());
		dbEntity.setName(entity.getName());
		dbEntity.setDescription(entity.getDescription());
		dbEntity.setOrderId(entity.getOrderId());
		this.menuRepository.update(dbEntity);
		updateParentChildrenOrderId(vo);
		this.reloadMenus(vo.getSysType());
		return entity;
	}

	@Transactional
	public void updateMenuDesc(IndexVo vo) throws Exception {
		MenuEntity entity = this.findEntity(vo.getMid());
		entity.setDescription(vo.getMenuDesc());
	}

	@Transactional
	@Override
	public TreeChildVo addSys(TreeManagerVo vo) throws Exception {
		this.menuRepository.create(vo.getSysEntity());
		TreeChildVo child = this.getSysChildVo(vo.getSysEntity().getSysType(),
				vo.getSysEntity().getSysName());
		// vo.setSysType(vo.getSysEntity().getSysType());
		return child;
	}

	public MenuEntity findEntity(String mid) throws Exception {
		return this.menuRepository.findEntity(mid);
	}


	@Override
	public List<TreeChildVo> getMenuTree(String sysType) throws Exception {
		List<Map> list = allSysMenus.get(sysType);
		if (list == null) {
			this.reloadMenus(sysType);
			list = allSysMenus.get(sysType);
		}
		Map<String, List<TreeChildVo>> assortChild = (Map<String, List<TreeChildVo>>) list
				.get(1);
		List<TreeChildVo> voList = assortChild.get(null);
		if (voList == null) {
			return new Vector<TreeChildVo>();
		} else {
			return new Vector<TreeChildVo>(voList);
		}
	}

	@Override
	public TreeChildVo getTreeById(String id, String sysType) throws Exception {
		List<Map> list = allSysMenus.get(sysType);
		if (list == null) {
			this.reloadMenus(sysType);
			list = allSysMenus.get(sysType);
		}
		Map<String, TreeChildVo> menus = (Map<String, TreeChildVo>) list.get(0);
		return menus.get(id);
	}

	public List<TreeChildVo> loadTreeR(String mid, String sysType)
			throws Exception {
		List<TreeChildVo> treeR = new ArrayList<TreeChildVo>();
		TreeChildVo topNode = this.getSysChildVo(sysType, null);
		while (StringUtils.isNotBlank(mid)) {
			TreeChildVo node = this.getTreeById(mid, sysType);
			if (node == null) {
				break;
			}
			treeR.add(node);
			mid = node.getPid();
		}
		List<TreeChildVo> result = new ArrayList<TreeChildVo>();
		result.add(topNode);
		for (int i = treeR.size() - 1; i >= 0; i--) {
			result.add(treeR.get(i));
		}
		return result;
	}

	/**
	 * 分类menus,且装载children
	 * 
	 * @return
	 */
	private void assortChild(String sysType) {
		List<Map> list = allSysMenus.get(sysType);
		Map<String, TreeChildVo> menus = (Map<String, TreeChildVo>) list.get(0);
		Map<String, List<TreeChildVo>> assortChild = (Map<String, List<TreeChildVo>>) list
				.get(1);
		assort(sysType, menus.values(), assortChild);
	}

	private void assort(String sysType, Collection<TreeChildVo> collection,
			Map<String, List<TreeChildVo>> assortChild) {
		for (TreeChildVo menu : collection) {
			List<TreeChildVo> set = null;
			if (assortChild.get(menu.getPid()) == null) {
				set = new ArrayList<TreeChildVo>();
				assortChild.put(menu.getPid(), set);
			} else {
				set = assortChild.get(menu.getPid());
			}
			set.add(menu);
		}
		this.sortChildren(assortChild);
		// 子节点装载进对象
		for (TreeChildVo menu : collection) {
			List children = assortChild.get(menu.getId() + "");// 获取该节点下的子节点
			if (children != null && children.size() != 0) {
				menu.setChildren(new ArrayList<TreeChildVo>(children));
			}
		}
	}

	@SuppressWarnings("unused")
	private List<TreeChildVo> getAvailMenuList(List<String> mList,
			String sysType) throws Exception {
		List<Map> list = allSysMenus.get(sysType);
		if (list == null) {
			this.reloadMenus(sysType);
			list = allSysMenus.get(sysType);
		}
		Map<String, TreeChildVo> menus = (Map<String, TreeChildVo>) list.get(0);
		List<TreeChildVo> availList = new ArrayList<TreeChildVo>();
		for (String mid : menus.keySet()) {
			if (mList.contains(mid)) {
				TreeChildVo menu = menus.get(mid);
				TreeChildVo node = new TreeChildVo();
				node.setId(mid);
				node.setOrderId(menu.getOrderId());
				node.setPid(menu.getPid());
				node.setText(menu.getText());
				node.setUrl(menu.getUrl());
				availList.add(node);
			}
		}
		return availList;
	}

	/**
	 * 排序
	 * 
	 * @param sysType
	 */
	private void sortChildren(Map<String, List<TreeChildVo>> assortChild) {
		// List<Map> list = allSysMenus.get(sysType);
		// Map<String, List<TreeChildVo>> assortChild = (Map<String,
		// List<TreeChildVo>>)list.get(1);
		for (List children : assortChild.values()) {
			Collections.sort(children, new Comparator<TreeChildVo>() {
				@Override
				public int compare(TreeChildVo arg0, TreeChildVo arg1) {
					if (arg1.getOrderId() == null) {
						return -1;
					}
					if (arg1.getOrderId() == null) {
						return 1;
					}
					if (arg0.getOrderId() < arg1.getOrderId()) {
						return -1;
					} else {
						return 1;
					}
				}
			});
		}
	}

	/**
	 * 更新同级节点下的顺序
	 * 
	 * @param vo
	 * @throws Exception
	 */
	private void updateParentChildrenOrderId(TreeManagerVo vo) throws Exception {
		TreeChildVo parentNode = vo.getParentNode();
		if (parentNode.getChildren() != null
				&& parentNode.getChildren().size() != 0) {
			for (TreeChildVo childNode : parentNode.getChildren()) {
				if (childNode == null) {
					continue;
				}
				if (StringUtils.equals(vo.getEntity().getCode(),
						childNode.getId())) {
					continue;// 本node在方法外部节点更新了。
				}
				MenuEntity childEntity = this.findEntity(childNode.getId());
				childEntity.setOrderId(childNode.getOrderId());
			}
		}
	}
	
	/**
	 * 封装系统类型树
	 * 
	 * @param sysType
	 * @param sysName
	 * @return
	 * @throws Exception
	 */
	public TreeChildVo getSysChildVo(String sysType, String sysName)
			throws Exception {
		if (StringUtils.isBlank(sysName)) {
			SystemEntity sys = this.getSystemEntity(sysType);
			sysName = sys.getSysName();
		}
		List<TreeChildVo> list = this.getMenuTree(sysType);
		TreeChildVo child = new TreeChildVo(list);
		child.setText(sysName);
		child.setId(sysType);
		return child;
	}

	@Override
	public List<TreeChildVo> getAllMenuTree() throws Exception {
		List<SystemEntity> allSys = getAllSysEntity();
		List<TreeChildVo> result = new ArrayList<TreeChildVo>();
		for (SystemEntity sys : allSys) {
			TreeChildVo child = this.getSysChildVo(sys.getSysType(),
					sys.getSysName());
			result.add(child);
		}
		return result;
	}
	/**
	 * 获取所有系统实体
	 * @return
	 */
	private List<SystemEntity> getAllSysEntity(){
		return this.menuRepository
		.findAll(SystemEntity.class);
	}
	
	private SystemEntity getSystemEntity(String sysType) throws Exception {
		SystemEntity sys = this.menuRepository.get(SystemEntity.class,
				sysType);
		return sys;
	}
	
//	/**
//	 * 从角色功能权限中获取有效的树
//	 * 
//	 * @param mList
//	 * @param sysType
//	 * @return
//	 * @throws Exception
//	 */
//	@Override
//	public List<TreeChildVo> getTreeByRoleMList(List<String> mList,
//			String sysType) throws Exception {
//		List<TreeChildVo> availList = getAvailMenuList(mList, sysType);
//		Map<String, List<TreeChildVo>> assortChild = new HashMap<String, List<TreeChildVo>>();
//		assort(sysType, availList, assortChild);
//		List<TreeChildVo> voList = assortChild.get(null);
//		if (voList == null) {
//			return new Vector<TreeChildVo>();
//		} else {
//			return new Vector<TreeChildVo>(voList);
//		}
//	}
}
